#ifndef _GOVT_EVENTS_HPP
#define _GOVT_EVENTS_HPP
/*******************************************************************************
 ** Government Sanctioned Espionage RPG                                       **
 ** http://www.government-sanctioned.us/                                      **
 **===========================================================================**
 ** Name: events.hpp                                                          **
 ** Description: Events for event-driven gameplay.                            **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2012  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// Modified $Date: 2012-08-14 20:47:30 -0600 (Tue, 14 Aug 2012) $ by $Author: unknown $
#include <queue>
#include <vector>
#include <deque>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>
#include "common.hpp"
#include "uuid.hpp"

#define events_hpp_ID   "$Id: events.hpp 69068 2012-08-15 02:47:30Z unknown $"

#define DEFAULT_EXPIRATION	15	// 15sec

//! The enumeration of all supported events in the game
// These can more easily be pulled directly from the game db ~gian
enum class EventType : uint64_t
{
	Unknown = 0x0000000000000000,
	AgencyJoined = 0x0000000000000001,
	AgencyQuit = 0x0000000000000002,
	AgencyBurned = 0x0000000000000004,
	AgencyDemoted = 0x0000000000000008,
	AgencyPromoted = 0x0000000000000010,
	AggroDropped = 0x0000000000000020,
	AggroGained = 0x0000000000000040,
	AttackBegin = 0x0000000000000080,
	AttackEnd = 0x0000000000000100,
	CallForHelp = 0x0000000000000200,
	CastSpell = 0x0000000000000400,
	EnemyDeath = 0x0000000000000800,
	EmoteTarget = 0x0000000000001000,
	EnemyCountIncrease = 0x0000000000002000,
	EnemyCountDecrease = 0x0000000000004000,
	EnterRoom = 0x0000000000008000,
	Follow = 0x0000000000010000,
	FriendlyDeath = 0x0000000000020000,
	FriendlyVPLow = 0x0000000000040000,
	EnemyVPLow = 0x0000000000080000,
	ObjectRecvDamage = 0x0000000000100000,
	QuestOffered = 0x0000000000200000,
	QuestAccepted = 0x0000000000400000,
	QuestDeclined = 0x0000000000800000,
	QuestCompleted = 0x0000000001000000,
	QuestEvent = 0x0000000002000000,
	SelfConditionChange = 0x0000000004000000,
	SelfEvade = 0x0000000008000000,
	SelfLowHealth = 0x0000000010000000,
	SpellHit = 0x0000000020000000,
	TargetConditionChange = 0x0000000040000000,
	WeaponWielded = 0x0000000080000000,
	NPCDeath = 0x0000000100000000,
	PlayerDeath = 0x0000000200000000,
	ExitRoom = 0x0000000400000000,
	ReputationAttacked = 0x0000000800000000,
	ReputationKilled = 0x0000001000000000,
	ReputationBrandished = 0x0000002000000000,
	ReputationAided = 0x0000004000000000,
	ReputationGaveTo = 0x0000008000000000,
	ReputationStoleFrom = 0x0000010000000000,
	ReputationIntimidated = 0x0000020000000000,
	ReputationThreatened = 0x0000040000000000,
	ReputationMisdemeanor =0x0000080000000000,
	ReputationFelony = 0x0000100000000000,
	ReputationHarassed = 0x0000200000000000,
	ReputationBribed = 0x0000400000000000,
	WeaponUnwielded = 0x0000800000000000

};

enum class EventEnv { Global, Local };

//! The enumeration of all supported event triggers in the game
enum class TriggerType : unsigned short
{
	Unknown = 0x0000,
	Command = 0x0001,
	Interaction = 0x0002,
	Proximity = 0x0004,
	TimeBased = 0x0008,
	EventBased = 0x0010,
	Initialization = 0x0020,
	SkillCheck = 0x0040,
	Environmental = 0x0080,
	Damage = 0x0100,
	Condition = 0x0200,
	Combat = 0x0400
};

//! @class Event
//! @brief The given event to be fired
class Event
{
public:
	SMART_PTR_DECL(Event)

	Event() { global::UUIDFactory::Create(id); }
	Event(EventType et, TriggerType tt, entity_t src);
	virtual ~Event() {  }

	virtual void operator() (entity_t,EventType) { }

	void		Subscribe(entity_t e) { _subscribers.push_back(e); }
	void		Unsubscribe(entity_t e) {
		std::vector<entity_t>::iterator i;
		for (i = _subscribers.begin(); i != _subscribers.end(); ++i)
			if ((*i) == e)
				_subscribers.erase(i);
	}

	// Getters
	const boost::uuids::uuid &	ID() const { return id; }
	const std::vector<entity_t> &	Subscribers() const { return _subscribers; }
	const boost::posix_time::ptime & ExeTime() const { return exeTime; }

	// Setters
	void	Duration(boost::posix_time::ptime p) { duration = p; }


protected:
	boost::uuids::uuid	id;
	entity_t	source;
	EventType	type;
	TriggerType trigger;
	EventEnv	env;
	bool        isRepeating;
	ushort      radius;
	boost::posix_time::ptime      duration;
	boost::posix_time::ptime      exeTime;
	boost::posix_time::ptime      timestamp;
	boost::posix_time::ptime      expiration;
	entity_t 	room;
//	Position    pos;

	std::vector<entity_t>	_subscribers;
};

// TimedEvent comparison functor
class TimedEventComp : public std::binary_function<Event*,Event*,bool>
{
public:
	bool operator() (const first_argument_type & left, second_argument_type & right)
	{
		return left->ExeTime() > right->ExeTime();
	}
};

//! @class EventManager
//! @brief A class to manage all the game's events
class EventManager
{
public:

	void	Add(Event::pointer e) { eq.push(e); }
	void	Process();

private:
	std::priority_queue<Event::pointer, std::deque<Event::pointer> TimedEventComp> eq;
};




namespace global
{
// The global event queue
//extern std::queue<Event> EventQueue;
// The global timed event queue
//extern std::priority_queue<TimedEvent *, std::vector<TimedEvent*>, TimedEventComp> TimedEventQueue;
}

#endif /* EVENTS_HPP */
